﻿using DVPCameraType;
using HalconDotNet;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace YJYpublicClass
{
    public class CameraDS2
    {
        //外部可设置变量
        public string CameraSNname { get; set; } = "";
        public string Savepath { get; set; } = "DS相机";
        public double Exposuretime { get; set; } = 1000;


        public double Gain { get; set; } = 1;
        [XmlIgnore]
        public int CamreOpenFlag { get; set; } = 0; //相机打开状态
        [XmlIgnore]
        public Boolean m_bGrabbing = false;//开始取图状态
        [XmlIgnore]
        public Boolean getNewImageFlag = false;

        //内部使用变量
        [XmlIgnore]
        public uint m_handle = 0;
        [XmlIgnore]
        public bool m_bAeOp = false;
        [XmlIgnore]
        public int m_n_dev_count = 0;
        [XmlIgnore]
        public string m_strFriendlyName;
        [XmlIgnore]
        public IntPtr m_ptr_wnd = new IntPtr();
        [XmlIgnore]
        public IntPtr m_ptr = new IntPtr();
        // public bool m_b_start = false;

        // Display param
        [XmlIgnore]
        public Stopwatch m_Stopwatch = new Stopwatch();
        [XmlIgnore]
        public Double m_dfDisplayCount = 0;
        [XmlIgnore]
        public static dvpCameraInfo[] m_info = new dvpCameraInfo[16];
        [XmlIgnore]
        public int m_CamCount = 0;
        [XmlIgnore]
        public HObject Image = new HObject();
        //[XmlIgnore]
        //Image<Bgr, byte> tempreimg = null;


        //[XmlIgnore]
        //Image<Gray, byte> tempreimggray = null;

        //[XmlIgnore]
        //public IInputOutputArray[] images = new IInputOutputArray[10];

        [XmlIgnore]
        public List<string> reMES { get; set; } = new List<string>();
        [XmlIgnore]
        public static List<string> CameraSnNames = new List<string>();

        [XmlIgnore]
        public double zhenlv { get; set; } = 0;
        [XmlIgnore]
        public double haoshi { get; set; } = 0;

        //回调函数接口
        [XmlIgnore]
        private DVPCamera.dvpStreamCallback _proc;
        [XmlIgnore]
        Stopwatch tw1 = new Stopwatch();
        [XmlIgnore]
        Stopwatch tw2 = new Stopwatch();
        [XmlIgnore]
        int i = 0;
        [XmlIgnore]
        public int tupianindex = 0;
        [XmlIgnore]
        public int lasttupianindex = -1;
        [XmlIgnore]
        public PictureBox PictureBox1 = null;

        //搜索相机
        public static void Enumdevlist()
        {
            dvpStatus status;
            uint i, n = 0;
            dvpCameraInfo dev_info = new dvpCameraInfo();
            // "n" represent the number of cameras that is enumerated successfully, the drop-down list contains each camera's FriendlyName.
            CameraSnNames.Clear();
            // Get the number of cameras that has been connected to a computer.
            status = DVPCamera.dvpRefresh(ref n);
            Debug.Assert(status == dvpStatus.DVP_STATUS_OK);
            // m_n_dev_count = (int)n;
            if (status == dvpStatus.DVP_STATUS_OK)
            {
                int m_CamCount = 0;
                for (i = 0; i < n; i++)
                {
                    // Acquire each camera's information one by one.
                    status = DVPCamera.dvpEnum(i, ref dev_info);

                    if (status == dvpStatus.DVP_STATUS_OK)
                    {
                        m_info[m_CamCount] = dev_info;
                        CameraSnNames.Add(dev_info.UserID);
                        m_CamCount++;
                    }
                    else
                    {
                        Debug.Assert(status == dvpStatus.DVP_STATUS_OK);
                    }
                }
            }

        }
        //打开相机
        public void OpenCamera(int index)
        {
            reMES.Clear();
            if (index >= CameraSnNames.Count)
            {
                reMES.Add("索引超出范围");
                return;
            }
            string name = CameraSnNames[index];
            OpenCamerabyname(name);

        }
        public void OpenCamerabyname(string name)
        {
            reMES.Clear();
            dvpStatus status = dvpStatus.DVP_STATUS_OK;

            if (!IsValidHandle(m_handle))
            {
                if (name != "")
                {
                    status = DVPCamera.dvpOpenByUserId(name, dvpOpenMode.OPEN_NORMAL | dvpOpenMode.OPEN_DEBUG, ref m_handle);

                    if (status != dvpStatus.DVP_STATUS_OK)
                    {
                        reMES.Add("打开相机失败!");
                        return;
                    }

                    //如果需要显示图像，用户需要注册一个回调函数，并在注册的回调函数中完成绘图操作
                    //注意:在回调函数中绘图可能会对使用“dvpGetFrame”获取图像数据产生一些延迟
                    _proc = _dvpStreamCallback;
                    status = DVPCamera.dvpRegisterStreamCallback(m_handle, _proc, dvpStreamEvent.STREAM_EVENT_FRAME_THREAD, m_ptr);

                    if (status != dvpStatus.DVP_STATUS_OK)
                    {
                        reMES.Add("打开相机失败!");
                        return;
                    }
                    //设置曝光
                    //设置线扫长度，也可以是不定高度，触发返回
                    //其他初始化事项
                    CamreOpenFlag = 1;

                }
            }
            else
            {
                reMES.Add("相机占用或打开");
                //检查相机视频流的状态
                //dvpStreamState StreamState = new dvpStreamState();
                //status = DVPCamera.dvpGetStreamState(m_handle, ref StreamState);
                //Debug.Assert(status == dvpStatus.DVP_STATUS_OK);
                //if (StreamState == dvpStreamState.STATE_STARTED)
                //{
                //    ////初始化显示数量为0
                //    m_dfDisplayCount = 0;

                //    //停止视频流
                //    status = DVPCamera.dvpStop(m_handle);
                //    Debug.Assert(status == dvpStatus.DVP_STATUS_OK);

                //}
                ////关闭相机
                //status = DVPCamera.dvpClose(m_handle);
                //Debug.Assert(status == dvpStatus.DVP_STATUS_OK);
                //m_handle = 0;

            }

        }
        //关闭相机
        public void CloseCamera()
        {
            dvpStreamState StreamState = new dvpStreamState();
            dvpStatus status = DVPCamera.dvpGetStreamState(m_handle, ref StreamState);
            if (StreamState == dvpStreamState.STATE_STARTED)
            {
                // init display count is 0
                m_dfDisplayCount = 0;
                // stop camera
                status = DVPCamera.dvpStop(m_handle);
                Debug.Assert(status == dvpStatus.DVP_STATUS_OK);
            }
            m_bGrabbing = false;
            status = DVPCamera.dvpClose(m_handle);
            if (status == dvpStatus.DVP_STATUS_OK)
            {
                m_handle = 0;
                CamreOpenFlag = 0;
            }
            else
            {
                reMES.Add("关闭相机失败");
            }

        }

        //开始取流
        public void StartGrab()
        {
            dvpStreamState state = dvpStreamState.STATE_STOPED;
            dvpStatus status = dvpStatus.DVP_STATUS_UNKNOW;

            if (IsValidHandle(m_handle))
            {
                // Implement a button to start and stop according to the current video's status.
                status = DVPCamera.dvpGetStreamState(m_handle, ref state);
                Debug.Assert(status == dvpStatus.DVP_STATUS_OK);
                if (state == dvpStreamState.STATE_STARTED)
                {
                    status = DVPCamera.dvpStop(m_handle);
                    Debug.Assert(status == dvpStatus.DVP_STATUS_OK);
                    m_bGrabbing = status == dvpStatus.DVP_STATUS_OK ? false : true;

                }
                else
                {

                    status = DVPCamera.dvpStart(m_handle);
                    Debug.Assert(status == dvpStatus.DVP_STATUS_OK);
                    m_bGrabbing = status == dvpStatus.DVP_STATUS_OK ? true : false;
                }
            }
        }
        public void StopGrab()
        {
            dvpStreamState state = dvpStreamState.STATE_STOPED;
            dvpStatus status = dvpStatus.DVP_STATUS_UNKNOW;
            if (IsValidHandle(m_handle))
            {
                status = DVPCamera.dvpGetStreamState(m_handle, ref state);
                Debug.Assert(status == dvpStatus.DVP_STATUS_OK);
                if (state == dvpStreamState.STATE_STARTED)
                {
                    status = DVPCamera.dvpStop(m_handle);
                    Debug.Assert(status == dvpStatus.DVP_STATUS_OK);
                    m_bGrabbing = status == dvpStatus.DVP_STATUS_OK ? false : true;

                }
            }
        }

        // Callback function that is used for receiving data.
        public int _dvpStreamCallback(/*dvpHandle*/uint handle, dvpStreamEvent _event, /*void **/IntPtr pContext, ref dvpFrame refFrame, /*void **/IntPtr pBuffer)
        {
            bool bDisplay = false;

            if (!tw1.IsRunning)
            {
                tw1.Restart();
            }
            tw2.Reset();
            tw2.Start();

            if (m_dfDisplayCount == 0)
            {
                m_Stopwatch.Restart();
                bDisplay = true;
            }
            else
            {
                if (m_Stopwatch.ElapsedMilliseconds - (long)(m_dfDisplayCount * 33.3f) >= 33)
                {
                    bDisplay = true;
                }
            }
            //直接转化成halcon图像，或者转化成mat图像
            int width = refFrame.iWidth;
            int height = refFrame.iHeight;
            //图像是否旋转了90度，旋转了90度帧宽度和高度要互换
            if (refFrame.bRotateState)
            {
                height = refFrame.iWidth;
                width = refFrame.iHeight;
            }
            try
            {
                //释放ho_image
                //转程halcon对象
                if (Image != null)
                {
                    Image.Dispose();
                    Image = null;
                }

                if (refFrame.format == dvpImageFormat.FORMAT_BGR24)
                {
                    HOperatorSet.GenImageInterleaved(out Image, pBuffer, "bgr", width, height, 0, "byte", 0, 0, 0, 0, -1, 0);
                }
                else if (refFrame.format == dvpImageFormat.FORMAT_MONO)
                {
                    HOperatorSet.GenImage1Extern(out Image, "byte", width, height, pBuffer, 0);
                }
                //
                //if (refFrame.format == dvpImageFormat.FORMAT_BGR24)
                //{
                //    tempreimg = new Image<Bgr, byte>(width, height, width * 3, pBuffer);
                //    // Imagebags[CurrentImagenum2] = tempreimg.Mat.Clone();
                //}
                //else if (refFrame.format == dvpImageFormat.FORMAT_MONO)
                //{
                //    //tempreimg  = new Image<Gray, byte>(width, height, width * 1, pBuffer);
                //    // Imagebags[CurrentImagenum2] = tempreimggray.Mat.Clone();
                //}


                //PictureBox1.Image =((Image<Bgr, byte>)tempreimg).ToBitmap();
                tw2.Stop();
                haoshi = tw2.ElapsedMilliseconds;
                i++;
                zhenlv = i / 1.0 / tw1.ElapsedMilliseconds * 1000;
                //注意清零，
                if (tw1.ElapsedMilliseconds > 60 * 1000 || i > 10000)
                {
                    tw1.Restart();
                    i = 0;

                }
                getNewImageFlag = true;

            }
            catch (System.Exception ex)
            {
                reMES.Add(ex.Message.ToString());
            }

            return 0;
        }

        public bool IsValidHandle(uint handle)
        {
            bool bValidHandle = false;
            dvpStatus status = DVPCamera.dvpIsValid(handle, ref bValidHandle);
            if (status == dvpStatus.DVP_STATUS_OK)
            {
                return bValidHandle;
            }
            return false;
        }

        public Boolean SetExposuretime(double Exposuretime)
        {
            reMES.Clear();
            Boolean resultb = false;
            double fExpoTime = 0.0f;
            dvpDoubleDescr ExpoTimeDescr = new dvpDoubleDescr(); ;
            dvpStatus status;

            if (CamreOpenFlag != 1)
            {
                reMES.Add("相机未打开");
                return resultb;
            }
            // Get the descriptive information about the exposure time.
            status = DVPCamera.dvpGetExposureDescr(m_handle, ref ExpoTimeDescr);
            if (status != dvpStatus.DVP_STATUS_OK)
            {
                reMES.Add("获取失败");
                // Set the range of the exposure time.
                return false;

            }
            if (Exposuretime <= ExpoTimeDescr.fMin || Exposuretime >= ExpoTimeDescr.fMax)
            {
                reMES.Add("设置值超限");
                return resultb;
            }

            //设置曝光
            status = DVPCamera.dvpSetExposure(m_handle, Exposuretime);

            // Get the initial value of the exposure time.

            if (status == dvpStatus.DVP_STATUS_OK)
            {
                reMES.Add("设置成功");
                return true;
            }
            else
            {
                reMES.Add("设置失败");
                return false;
            }

        }

        public Boolean setGain(double gain)
        {
            reMES.Clear();
            dvpStatus status;
            float fAnalogGain = 0.0F;
            dvpFloatDescr AnalogGainDescr = new dvpFloatDescr();
            if (CamreOpenFlag != 1)
            {
                reMES.Add("相机未打开");
                return false;
            }
            // Get the descriptive information about the analog gain.
            status = DVPCamera.dvpGetAnalogGainDescr(m_handle, ref AnalogGainDescr);

            if (status != dvpStatus.DVP_STATUS_OK)
            {
                reMES.Add("模拟增益获取失败");
                return false;

            }
            if (gain <= AnalogGainDescr.fMin || gain >= AnalogGainDescr.fMax)
            {
                reMES.Add("设置值超限");
                return false;
            }

            status = DVPCamera.dvpSetAnalogGain(m_handle, (float)gain);
            if (status == dvpStatus.DVP_STATUS_OK)
            {
                reMES.Add("设置成功");
                return true;
            }
            else
            {
                reMES.Add("设置失败");
                return false;
            }
        }



        public void SetConfig()
        {
            Frm_DS相机设置 frm = new Frm_DS相机设置(this);
            frm.Show();
        }
    }
}
